package cn.xinfei.xdecision.engine.runner.executor.strategy.component;

import cn.xinfei.xdecision.common.model.component.ComponentVo;
import cn.xinfei.xdecision.common.model.component.decisiontable.vo.DecisionTablesDetailVo;
import cn.xinfei.xdecision.common.model.component.decisiontable.vo.DecisionTablesVersionVo;
import cn.xinfei.xdecision.common.model.component.decisiontable.vo.DecisionTablesVo;
import cn.xinfei.xdecision.common.model.component.strategyout.StrategyOutput;
import cn.xinfei.xdecision.common.model.datax.datamanage.Field;
import cn.xinfei.xdecision.common.service.component.decisiontable.DecisionTablesDetailService;
import cn.xinfei.xdecision.common.service.component.decisiontable.DecisionTablesService;
import cn.xinfei.xdecision.common.service.component.decisiontable.DecisionTablesVersionService;
import cn.xinfei.xdecision.common.service.component.strategyout.StrategyOutputService;
import cn.xinfei.xdecision.common.service.datax.datamanage.FieldService;
import cn.xinfei.xdecision.common.utils.enums.enginex.ComponentTypeEnum;
import cn.xinfei.xdecision.common.utils.enums.enginex.ConditionValueTypeEnum;
import cn.xinfei.xdecision.common.utils.util.JsonUtils;
import cn.xinfei.xdecision.common.vo.FieldInfoVo;
import cn.xinfei.xdecision.constant.EngineResultEnum;
import cn.xinfei.xdecision.engine.runner.context.XDecisionContext;
import cn.xinfei.xdecision.engine.runner.executor.ComponentHandler;
import cn.xinfei.xdecision.engine.runner.executor.XRunner;
import cn.xinfei.xdecision.engine.runner.executor.handler.DecisionTableNodeHandler;
import cn.xinfei.xdecision.engine.runner.executor.model.StateTransmitModel;
import cn.xinfei.xdecision.engine.runner.executor.strategy.EngineComponentRunner;
import cn.xinfei.xdecision.engine.runner.metadata.MetadataProvider;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@XRunner
@Slf4j
@Service
public class DecisionTablesComponent extends EngineComponentRunner {

    @Resource
    private DecisionTableNodeHandler decisionTableNodeHandler;

    @Autowired
    private DecisionTablesDetailService detailService;

    @Autowired
    private FieldService fieldService;

    @Autowired
    protected MetadataProvider metadataProvider;

    @Autowired
    protected StrategyOutputService strategyOutputService;

    @Autowired
    private DecisionTablesVersionService decisionTablesVersionService;

    @Resource
    private DecisionTablesService decisionTablesService;

    @Override
    public void before(ComponentHandler nodeHandler) {
        String componentCode = nodeHandler.getCode();
        ComponentVo componentVo = nodeHandler.getComponentVo();
        Long versionNo = componentVo.getVersionNo();
        DecisionTablesVo decisionTablesVo = decisionTablesService.queryByVersionId(componentCode, versionNo);
        Long versionId = decisionTablesVo.getExecuteVersion().getId();
        componentVo.setVersionId(versionId);
    }

    @Override
    public String getServiceName() {
        return EngineComponentRunner.PRE + ComponentTypeEnum.DECISION_TABLES.getType();
    }

    @Override
    public Map<String, StrategyOutput> getOutputFieldInfo(ComponentHandler nodeHandler) {
        Map<String, StrategyOutput> strategyOutputMap = super.getOutputFieldInfo(nodeHandler);
        try {
            Map<String, FieldInfoVo> fieldInfo = metadataProvider.getFieldInfo();
            String componentCode = nodeHandler.getCode();
            ComponentVo componentVo = nodeHandler.getComponentVo();
            Long versionNo = componentVo.getVersionNo();

            List<DecisionTablesVersionVo> decisionTablesVersionVos = decisionTablesVersionService.queryVersionByTablesCodes(componentCode, versionNo);
            for (DecisionTablesVersionVo decisionTablesVersionVo : decisionTablesVersionVos) {
                String resultFieldCode = decisionTablesVersionVo.getResultFieldCode();

                FieldInfoVo fieldInfoVo = fieldInfo.get(resultFieldCode);
                StrategyOutput output = new StrategyOutput();
                output.setFieldCode(resultFieldCode);
                output.setFieldValue(decisionTablesVersionVo.getDefaultValue());
                output.setVarValueType(fieldInfoVo.getValueType());
                output.setValueType(ConditionValueTypeEnum.VARIABLE.getCode());
                output.setStage(fieldInfoVo.getStage());
                output.setFixed(true);
                strategyOutputMap.put(resultFieldCode, output);
            }
        } catch (Exception e) {
            log.error("getOutputFieldInfo:获取指标异常,error={},nodeHandler={}", e.getMessage(), JsonUtils.toJsonString(nodeHandler), e);
        }
        return strategyOutputMap;
    }

    @Override
    public void getNodeFieldValue(Set<String> fieldSet, String nodeCode) throws Exception {

    }

    @Override
    public Map<String, FieldInfoVo> getInputFieldInfo(ComponentHandler nodeHandler) {

        String componentCode = nodeHandler.getComponentCode();
        Map<String, FieldInfoVo> fieldVos = new HashMap<>();
        Set<String> fieldCodes = new HashSet<>();
        try {
            Map<String, FieldInfoVo> fieldInfo = metadataProvider.getFieldInfo();
            ComponentVo componentVo = nodeHandler.getComponentVo();
            Long versionId = componentVo.getVersionId();
            List<DecisionTablesDetailVo> detailVos = detailService.queryDecisionTablesByVersionId(versionId);
            fieldCodes.addAll(detailVos.stream().map(d -> d.getFieldCode()).collect(Collectors.toSet()));
            List<Field> fields = fieldService.queryByEns(fieldCodes);
            fields.forEach(field -> {
                String fieldCode = field.getFieldCode();
                FieldInfoVo value = fieldInfo.get(fieldCode);
                if (value != null) {
                    fieldVos.put(fieldCode, value);
                }
            });

        } catch (Exception e) {
            log.error("DecisionTablesNode,getInputFieldInfo:获取决策表指标异常,error={},componentCode={}", e.getMessage(), componentCode, e);
        }
        return fieldVos;
    }


    @Override
    public StateTransmitModel runNode(ComponentHandler nodeHandler) {


        String componentCode = nodeHandler.getComponentCode();
        ComponentVo componentVo = nodeHandler.getComponentVo();
        Long versionNo = componentVo.getVersionNo();
        DecisionTablesVo decisionTablesVersionVo = decisionTablesService.queryByVersionId(componentCode, versionNo);
        if (null == decisionTablesVersionVo) {
            return XDecisionContext.getContext().getStateContext().setEngineResultEnum(EngineResultEnum.NO_EXISTS);
        }
        DecisionTablesVersionVo executeVersion = decisionTablesVersionVo.getExecuteVersion();
        Object executeResult = decisionTableNodeHandler.executeDecisionTables(executeVersion);
        String resultFieldEn = executeVersion.getResultFieldCode();
        if (null != executeResult) {
            setOutput(nodeHandler, resultFieldEn, executeResult);
        } else {
            //未命中输出，默认值
            setOutput(nodeHandler, resultFieldEn, executeVersion.getDefaultValue());
        }

        return XDecisionContext.getContext().getStateContext().setEngineResultEnum(EngineResultEnum.SUCCESS_END);
    }


}
